package com.cekanet.mybudget.dbutils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import javax.jdo.Query;



public class StatementHandler {
	private String userId;
		
	public StatementHandler(String userId){
		this.userId=userId;
	}
	public StatementItem alterItem(StatementItem statementItem) throws ProtectionException{
		//Use this method to add or alter a StatementItem
		if (statementItem.getOwnerId() == null)
			statementItem.setOwnerId(this.userId);
		else
			ownerCheck(statementItem, this.userId);
		
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try{
			tx.begin();
			pm.makePersistent(statementItem);
			tx.commit();
			
		}catch(JDOUserException e){
			throw e;
		}finally{
			if (tx.isActive())
				tx.rollback();
		    pm.close();
		}
		return statementItem;
		
		
	}
	public StatementItem getItem(Long key) throws ProtectionException{
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		StatementItem statementItem;
		try{
			tx.begin();
			statementItem = pm.getObjectById(StatementItem.class, key);
			tx.commit();
		}catch(JDOUserException e){
			throw e;
		}finally{
			if (tx.isActive())
				tx.rollback();
		    pm.close();
		}
		ownerCheck(statementItem, this.userId);
		return statementItem;
	}
	
	public void deleteStatementItem(StatementItem statementItem)throws ProtectionException{
		ownerCheck(statementItem, this.userId);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Transaction tx = pm.currentTransaction();
		try{
			tx.begin();
			pm.makePersistent(statementItem);
			pm.deletePersistent(statementItem);
			tx.commit();
		}catch(JDOUserException e){
			throw e;
		}finally{
			if (tx.isActive())
				tx.rollback();
		    pm.close();
		}
	}
	public void deleteStatementItem(Long key) throws ProtectionException{
		this.deleteStatementItem(this.getItem(key));
	}

	
	private void ownerCheck(StatementItem si, String ownerId) throws ProtectionException{
		if (!si.getOwnerId().equals(ownerId))
			throw new ProtectionException("Error: Cannot alter StatementItem: the current userId doesn'r match the StatementItem owner.\n" );
	}
	
	
	public List<StatementItem> getUserStatement() throws JDOUserException {
		List<StatementItem> retSil;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q;
		
		q = pm.newQuery(StatementItem.class);
		q.setFilter("userId == userIdParam");
		
		q.setOrdering("date desc");
		q.declareParameters("String userIdParam");
		
		try{
			@SuppressWarnings("unchecked")
			List<StatementItem> sil = (List<StatementItem>) q.execute(this.userId);
			retSil = new ArrayList<StatementItem>(sil);
		}catch (JDOUserException e){
			throw e;
		}finally{
			q.closeAll();
		    pm.close();
		}
		
		return retSil;
	}
	
	public List<String> getUserItemNameList(){
		List<String> returningList;
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q;
		
		q = pm.newQuery (StatementItem.class);
		q.declareParameters("String userIdParam");
		q.setFilter("userId == userIdParam");
		q.setOrdering("name asc");
		q.setResult ("distinct name");
		
		try{
			@SuppressWarnings("unchecked")
			List<String> results = (List<String>)q.execute (this.userId);
			returningList = new ArrayList<String>(results);
		}catch (JDOUserException e){
			throw e;
		}finally{
			q.closeAll();
		    pm.close();
		}

		return returningList;
	}
	
	
	@SuppressWarnings("unchecked")
	public List<StatementItem> query(Date startDate, Date stopDate, String name, String description){
		
		List <StatementItem> queryResults;
		
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q;
		
		
		
		String query ="userId == userIdParam" +
				" && this.date >= startDateParam " +
				" && this.date <= stopDateParam " ;
		
		if (!name.trim().isEmpty())
			query+=" && name ==  nameParam ";
		
		q = pm.newQuery(StatementItem.class);
		q.setFilter(query);
		
		q.setOrdering("date desc");
		
		q.declareParameters("java.lang.String userIdParam, " +
				"java.util.Date startDateParam, " +
				"java.util.Date stopDateParam," +
				"java.lang.String nameParam" );
		 
		
		@SuppressWarnings("rawtypes")
		HashMap parameters = new HashMap();
		
		parameters.put("userIdParam", this.userId);
		parameters.put("startDateParam", startDate);
		parameters.put("stopDateParam", stopDate);
		parameters.put("nameParam", name);

		
		try{
			List<StatementItem> sil = (List<StatementItem>) q.executeWithMap(parameters);
			queryResults = new ArrayList<StatementItem>(sil);
			
			//Workaroud please see: http://code.google.com/p/datanucleus-appengine/issues/detail?id=191
			String trimmedDescription = description.trim();
			if (!trimmedDescription.isEmpty()){
				queryResults = new ArrayList<StatementItem>();
				for (StatementItem item : sil){
					if (item.getDescription().contains(trimmedDescription))
						queryResults.add(item);
				}
			}else
				queryResults = new ArrayList<StatementItem>(sil);
			
		}catch (JDOUserException e){
			throw e;
		}finally{
			q.closeAll();
		    pm.close();
		}
		

		return queryResults;
		
	}
}
